﻿using Microsoft.Extensions.Configuration;
using Rw.Core.Common;
using SqlSugar;
using System;
using WH.Common.DbConfig.Model;
using WH.Common.Constant;

namespace WH.Common.DbConfig
{
    public class DbConfigExtensions : IConfigurationSource
    {

        public DbConfigExtensions()
        {
        }

        public IConfigurationProvider Build(IConfigurationBuilder builder)
        {
            return new DatabaseConfigurationProvider();
        }
    }

    public class DatabaseConfigurationProvider : ConfigurationProvider
    {

        public DatabaseConfigurationProvider()
        {
        }

        private static ISqlSugarClient? _AppsettingsDbcontext;

        /// <summary>
        /// 数据库（sqllite）
        /// </summary>
        public static ISqlSugarClient AppsettingsDbcontext
        {
            get
            {
                if (_AppsettingsDbcontext is null)
                {
                    _AppsettingsDbcontext = new SqlSugarScope(new ConnectionConfig()
                    {
                        ConnectionString = $"datasource={Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "appsettings.db")}",
                        DbType = DbType.Sqlite,
                        IsAutoCloseConnection = true,
                        ConfigureExternalServices = new ConfigureExternalServices()
                        {
                            EntityNameService = (type, entity) =>
                            {
                                entity.IsDisabledDelete = true;
                            }
                        },
                        MoreSettings = new ConnMoreSettings()
                        {
                            SqliteCodeFirstEnableDefaultValue = true //启用默认值
                        },
                        AopEvents = new AopEvents()
                        {
                            OnLogExecuting = (sql, pars) =>
                            {
                                //Console.WriteLine(sql);
                            }
                        }
                    });

                    _AppsettingsDbcontext.DbMaintenance.CreateDatabase();

                    _AppsettingsDbcontext.CodeFirst.InitTables(typeof(AppConfigEntity));
                }
                return _AppsettingsDbcontext;
            }
        }

        public override void Load()
        {
            var dics = new Dictionary<string, string>();

            //var nodes = GetTrees("0");

            var list = GetList();

            foreach (var item in list)
            {
                if (!string.IsNullOrWhiteSpace(item.Link) && !string.IsNullOrWhiteSpace(item.Value))
                {
                    //如果没有子集切数据类型为数组
                    if (item.DataType == 2 && list.Any(x => x.ParentId == item.Id) == false)
                    {
                        var arr = item.Value.Split(',');

                        foreach (var (d, i) in arr.Select((d, i) => (d, i)))
                        {
                            var link = $"{item.Link}:{i}";

                            if (dics.ContainsKey(link))
                            {
                                dics[link] = d;
                            }
                            else
                            {
                                dics.Add(link, d);
                            }
                        }
                    }
                    else
                    {
                        if (dics.ContainsKey(item.Link))
                        {
                            dics[item.Link] = item.Value;
                        }
                        else
                        {
                            dics.Add(item.Link, item.Value);
                        }
                    }
                }
            }

            Data = dics;

            OnReload();
        }

        private static IEnumerable<ConfigOutputDto>? _Appsettings;
        /// <summary>
        /// 配置项
        /// </summary>
        public IEnumerable<ConfigOutputDto> Appsettings
        {
            get
            {
                if (_Appsettings is null || _Appsettings.Any() == false)
                {
                    var data = AppsettingsDbcontext.Queryable<AppConfigEntity>().OrderByDescending(x => x.SortNo).ToList();

                    _Appsettings = data.Select(item => new ConfigOutputDto()
                    {
                        Id = item.Id,
                        ParentId = item.ParentId,
                        ComponentDefaultValue = item.ComponentDefaultValue,
                        ComponentType = item.ComponentType,
                        ConfigCategory = item.ConfigCategory,
                        DataType = item.DataType,
                        Description = item.Description,
                        Index = item.Index,
                        Key = item.Key,
                        //Link = item.Link,
                        SortNo = item.SortNo,
                        Summary = item.Summary,
                        Value = item.Value,
                        IsEnable = item.IsEnable,
                    }).ToList();
                }

                return _Appsettings;
            }
        }

        /// <summary>
        /// 获取配置树
        /// </summary>
        /// <param name="parentId"></param>
        /// <returns></returns>
        public List<ConfigOutputDto> GetTrees(string parentId)
        {
            List<ConfigOutputDto> appsettings = Appsettings.ToList();

            var nodes = appsettings.Where(x => x.ParentId == parentId).ToList();

            foreach (var item in nodes)
            {
                var parent = appsettings.Where(x => x.Id == parentId).FirstOrDefault();

                if (parent is null)
                {
                    item.Link = $"{item.Key}";
                }
                else
                {
                    if (parent.DataType == 2)
                    {
                        item.Link = $"{parent.Link}:{item.Index}:{item.Key}";
                    }
                    if (parent.DataType == 1)
                    {
                        item.Link = $"{parent.Link}:{item.Key}";
                    }
                }

                item.Children = GetTrees(item.Id);
            }

            return nodes;
        }

        /// <summary>
        /// 获取配置列表
        /// </summary>
        /// <param name="appsettings"></param>
        /// <returns></returns>
        public List<ConfigOutputDto> GetList(List<ConfigOutputDto>? appsettings = default, bool? onlyEnable = null)
        {
            var res = new List<ConfigOutputDto>();

            if (appsettings is null)
            {
                appsettings = Appsettings.ToList();

                if (onlyEnable is not null)
                {
                    appsettings = appsettings.Where(x => x.IsEnable == onlyEnable).ToList();
                }
            }

            foreach (var item in appsettings)
            {
                //var item = appsettings.Where(x => x.Id == node.Id).FirstOrDefault();

                //if (item is null)
                //{
                //    continue;
                //}

                var parent = Appsettings.Where(x => x.Id == item.ParentId).FirstOrDefault();

                if (parent is null)
                {
                    item.Link = $"{item.Key}";
                }
                else
                {
                    if (parent.DataType == 2)
                    {
                        item.Link = $"{parent.Link}:{item.Index}:{item.Key}";
                    }
                    if (parent.DataType == 1)
                    {
                        item.Link = $"{parent.Link}:{item.Key}";
                    }
                }

                var childrens = Appsettings.Where(x => x.ParentId == item.Id).ToList();
                if (childrens.Any())
                {
                    item.Children = GetList(childrens);
                }

                res.Add(item);
            }

            //(var i = 0; i < nodes.Count; i++)
            //{
            //    var node = nodes[i];
            //    var item = appsettings.Where(x => x.Id == node.Id).FirstOrDefault();

            //    if (item is null)
            //    {
            //        continue;
            //    }

            //    var parent = appsettings.Where(x => x.Id == item.ParentId).FirstOrDefault();

            //    if (parent is null)
            //    {
            //        item.Link = $"{item.Key}";
            //    }
            //    else
            //    {
            //        if (parent.DataType == 2)
            //        {
            //            item.Link = $"{parent.Link}:{item.Index}:{item.Key}";
            //        }
            //        if (parent.DataType == 1)
            //        {
            //            item.Link = $"{parent.Link}:{item.Key}";
            //        }
            //    }

            //    if (node.Children is not null)
            //    {
            //        item.Children = GetList(node.Children, appsettings);
            //        res.AddRange(item.Children);
            //    }

            //    res.Add(item);

            //}

            return res;
        }

        /// <summary>
        /// 配置索引
        /// </summary>
        /// <param name="link"></param>
        /// <returns></returns>
        public ConfigOutputDto? this[string link]
        {
            get
            {
                if (string.IsNullOrWhiteSpace(link))
                {
                    return default;
                }

                var item = GetList(onlyEnable: true).Where(x => x.Link?.Equals(link, StringComparison.OrdinalIgnoreCase) == true).FirstOrDefault();

                return item;
            }
        }

        /// <summary>
        /// 是否存在Key
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool ContainsKey(string key)
        {
            return Appsettings.Where(x => x.Key == key).Any();
        }

        /// <summary>
        /// 保存
        /// </summary>
        /// <param name="inputs"></param>
        /// <returns></returns>
        /// <exception cref="NullReferenceException"></exception>
        public async Task<int> SaveAsync(IList<ConfigInputDto> inputs, IConfiguration configuration)
        {
            var res = 0;
            foreach (var input in inputs)
            {
                if (input.ParentId != BusinessFunction.TopParentId)
                {
                    var exist = await AppsettingsDbcontext.Queryable<AppConfigEntity>().Where(x => x.Id == input.ParentId).AnyAsync();
                    if (exist == false)
                    {
                        throw new NullReferenceException("父级不存在");
                    }
                }

                AppConfigEntity? newConfig = await AppsettingsDbcontext.Queryable<AppConfigEntity>().Where(x => x.Id == input.Id).FirstAsync();

                if (newConfig is null)
                {
                    newConfig = new AppConfigEntity()
                    {
                        Id = Snowflake.GetNewId()
                    };
                }

                if (input.DataType is null)
                {
                    input.DataType = newConfig.DataType;
                }
                if (input.DataType is null)
                {
                    input.DataType = 1;
                }

                string? value = string.Empty;

                if (input.DataType == 1)
                {
                    value = input.Value?.ToString();
                }
                else if (input.DataType == 2)
                {
                    //var data = JsonConvert.DeserializeObject<List<string>>(JsonConvert.SerializeObject(input.Value));

                    //if (data is not null)
                    //{
                    //    value = string.Join(',', data);
                    //}

                    value = input.Value?.ToString();
                }

                newConfig.ParentId = input.ParentId;
                newConfig.Key = input.Key;
                newConfig.Value = value;
                newConfig.Description = input.Description;
                newConfig.SortNo = input.SortNo;
                newConfig.DataType = input.DataType;
                newConfig.ConfigCategory = input.ConfigCategory;
                newConfig.ComponentType = input.ComponentType;
                newConfig.ComponentDefaultValue = input.ComponentDefaultValue;
                newConfig.Index = input.Index;
                newConfig.IsEnable = input.IsEnable ?? true;

                res += await AppsettingsDbcontext.Storageable(newConfig).ExecuteCommandAsync();


                var config = await AppsettingsDbcontext.Queryable<AppConfigEntity>().Where(x => x.Key.Equals(newConfig.Key, StringComparison.OrdinalIgnoreCase) && x.Index == newConfig.Index && x.ParentId == newConfig.ParentId && x.Id != newConfig.Id).FirstAsync();

                if (config is not null)
                {
                    await AppsettingsDbcontext.Deleteable(config).ExecuteCommandAsync();
                }


                if (input.Children is not null && input.Children.Any())
                {
                    foreach (var child in input.Children)
                    {
                        child.ParentId = newConfig.Id;
                    }

                    await SaveAsync(input.Children, configuration);
                }
            }

            _Appsettings = null;

            var conf = configuration as IConfigurationRoot;

            if (conf is not null)
            {
                foreach (var p in conf.Providers)
                {

                    if (p is DatabaseConfigurationProvider)
                    {
                        p.Load();
                    }
                }
            }

            return res;
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public async Task<int> DeleteAsync(IList<string> ids)
        {
            var list = await AppsettingsDbcontext.Queryable<AppConfigEntity>().Where(x => ids.Contains(x.Id)).ToListAsync();
            int res = 0;

            foreach (var item in list)
            {
                var nodes = GetTrees(item.Id);

                var ls = GetList(nodes);

                res += await AppsettingsDbcontext.Deleteable<AppConfigEntity>().Where(x => ls.Select(l => l.Id).Contains(x.Id)).ExecuteCommandAsync();
            }

            res += await AppsettingsDbcontext.Deleteable<AppConfigEntity>().Where(x => list.Select(l => l.Id).Contains(x.Id)).ExecuteCommandAsync();

            _Appsettings = null;
            return res;
        }

        //public IDictionary<string, string> ConfigDics
        //{
        //    get
        //    {
        //        var nodes = GetTrees(Appsettings.ToList(), "0");

        //        var list = GetList(nodes);

        //        var dics = new Dictionary<string, string>();

        //        foreach (var item in list)
        //        {
        //            //dics.Add(item.Key, item.Value);
        //        }

        //        return dics;
        //    }
        //}
    }
}